
local function split(s, delim_pattern, n)
    local init = 1
    local result = {}
    while n > 0 do
        local delim
        if n == 1 then
            if init == s:len()+1 then break end
            delim = { 0, 0 }
        else
            delim = { s:find(delim_pattern, init) }
            if delim[1] == nil then
                if init <= s:len() then
                    table.insert(result, s:sub(init))
                end
                break
            end
        end
        table.insert(result, s:sub(init, delim[1]-1))
        init = delim[2] + 1
        n = n - 1
    end
    return result
end

local function sanitize_field(s)
    if s == nil then return nil end
    for i,v in ipairs(s) do
        local shards = split(v, "%s+", 3)
        s[i] = { shards[1], shards[2], _=shards[3] }
    end
    return s
end

local function sanitize_constraint(s)
    if s == nil then return nil end
    for i,v in ipairs(s) do
        local shards = split(v, "%s+", 3)
        local ns = { tag=shards[1], _=shards[3] }
        s[i] = ns
        for f in shards[2]:gmatch("[^,]+") do
            table.insert(ns, f)
        end
    end
    return s
end

return {
    enum = function(name, comment, es)
        if es == nil then
            es = comment
            comment = nil
        end

        local result = {
            tag = 'enum',
            name = name,
            _ = comment,
        }
        for i,v in ipairs(es) do
            local shards = split(v, "%s+", 2)
            result[i] = { shards[1], _=shards[2] }
        end
        return result
    end,

    entity = function(name, comment, ps)
        if ps == nil then
            ps = comment
            comment = nil
        end
        return {
            tag = 'entity',
            name = name,
            _ = comment,
            field = sanitize_field(ps.field),
            constraint = sanitize_constraint(ps.constraint),
            fn = ps.fn,
        }
    end,
}

